package com.mundus.engine.assets.vertex;

import java.nio.FloatBuffer;

import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import org.lwjgl.util.vector.Vector2f;
import org.lwjgl.util.vector.Vector3f;


public class VertexPosTexNor implements Vertex{
	private static final int POSITIONELEMENTCOUNT = 4;
	private static final int TEXCOORDELEMENTCOUNT = 2;
	private static final int NORMALELEMENTCOUNT = 3;
	
	private static int POSITIONBYTESCOUNT = POSITIONELEMENTCOUNT * ELEMENTBYTES;
	private static int TEXCOORDBYTESCOUNT  =TEXCOORDELEMENTCOUNT * ELEMENTBYTES;
	private static int NORMALBYTESCOUNT = NORMALELEMENTCOUNT * ELEMENTBYTES;

	private static int POSITIONBYTEOFFSET = 0;
	private static int TEXCOORDBYTEOFFSET = POSITIONBYTEOFFSET + POSITIONBYTESCOUNT;;
	private static int NORMALBYTEOFFSET = TEXCOORDBYTEOFFSET + TEXCOORDBYTESCOUNT;
	
	private static int ELEMENTCOUNT = POSITIONELEMENTCOUNT + TEXCOORDELEMENTCOUNT + NORMALELEMENTCOUNT;
	private static int SIZEINBYTES = POSITIONBYTESCOUNT  + TEXCOORDBYTESCOUNT + NORMALBYTESCOUNT;
	
	private Vector3f _position;
	private Vector2f _texCoord;
	private Vector3f _normal;

	public Vector3f getPositionv() { return _position;}
	public Vector2f getTexCoordv() { return _texCoord; }
	public Vector3f getNormalv(){return _normal;}
	
	public float[] getPositionf() { return new float[]{ _position.x, _position.y, _position.z};}
	public float[] getTexCoordf() {return new float[]{ _texCoord.x, _texCoord.y};}
	public float[] getNormalf() { return new float[]{ _normal.x, _normal.y, _normal.z};}

	public void setPosition(Vector3f position) { this._position = position; }
	public void setTexCoord(Vector2f texCoord) { this._texCoord = texCoord; }
	public void setNormal(Vector3f normal){ this._normal = normal; }
	
	public VertexPosTexNor(Vector3f position, Vector2f texCoord, Vector3f normal){
		this._position = position;
		this._texCoord = texCoord;
		this._normal = normal;
	}
	
	public float[] getElements(int elementCount){
		float[] elements = new float[elementCount];
		
		int i=0;
		//POSITION
		elements[i++] = this._position.x;
		elements[i++] = this._position.y;
		elements[i++] = this._position.z;
		elements[i++] = 1;
		//TEXCOORD
		elements[i++] = this._texCoord.x;
		elements[i++] = this._texCoord.y;
		//NORMAL
		elements[i++] = this._normal.x;
		elements[i++] = this._normal.y;
		elements[i++] = this._normal.z;
		
		return elements;
	}
	
	public int getVAO(Vertex[] vertices){
		FloatBuffer vBuffer = BufferUtils.createFloatBuffer(vertices.length * ELEMENTCOUNT);
		for(Vertex v : vertices){
			VertexPosTexNor vPTN = (VertexPosTexNor)v;
			vBuffer.put(vPTN.getElements(ELEMENTCOUNT));
		}
		vBuffer.flip();		
		
		int vaoId = GL30.glGenVertexArrays();
		GL30.glBindVertexArray(vaoId);

		int vboId = GL15.glGenBuffers();
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboId);
		GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vBuffer, GL15.GL_STATIC_DRAW);
		GL20.glVertexAttribPointer(0, POSITIONELEMENTCOUNT, GL11.GL_FLOAT, false, SIZEINBYTES, POSITIONBYTEOFFSET);
		GL20.glVertexAttribPointer(1, TEXCOORDELEMENTCOUNT, GL11.GL_FLOAT, false, SIZEINBYTES, TEXCOORDBYTEOFFSET);
		GL20.glVertexAttribPointer(2, NORMALELEMENTCOUNT,GL11.GL_FLOAT, false, SIZEINBYTES, NORMALBYTEOFFSET);
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);

		GL30.glBindVertexArray(0);
		
		return vboId;
	}
	
	public VertexType getVertexType(){
		return VertexType.VertexPosTexNor;
	}
	
	public void setActiveAttributes() {
		GL20.glEnableVertexAttribArray(0);
		GL20.glEnableVertexAttribArray(1);
		GL20.glEnableVertexAttribArray(2);
	}
}
